//
//  Validation.swift
//  TuJiaMerchant
//
//  Created by 何海涛 on 16/1/6.
//  Copyright © 2016年 途家. All rights reserved.
//

import Foundation

/// Validation result.
public class ValidationResult : NSObject {
    /// Key for validation, do use the property name.
    public var memberName : String
    public var errorMessage : String
    public var mapping : ViewDataMapping?
    
    public init(memberName name : String, errorMessage error : String) {
        self.memberName = name
        self.errorMessage = error
    }
}

/// Validation rule.
public class ValidationRule : NSObject {
    public var memberName : String
    public var displayName : String?
    public var errorMessage : String?
    
    public init(memberName name : String, displayName display : String? = nil) {
        self.memberName = name
        self.displayName = display
    }
    
    /**
     Validate method.
     
     - parameter val:     Current member value.
     - parameter allVals: All values of current validation.
     
     - returns: If val not valid return a ValidationResult, if not return nil.
     */
    public func validate(_ val : AnyObject?, allVals : [String:AnyObject]) -> ValidationResult? {
        return valid(val, allVals : allVals) ? nil
        : ValidationResult(memberName: self.memberName, errorMessage: self.errorMessage ?? errorFormat(val, allVals : allVals))
    }
    
    /**
     Validate sub method.
     
     - parameter val:     Current member value.
     - parameter allVals: All values of current validation.
     
     - returns: Valid or not.
     */
    public func valid(_ val : AnyObject?, allVals : [String:AnyObject]) -> Bool {
        return true
    }
    
    /**
     Error message formatter.
     
     - parameter val:     Current member value.
     - parameter allVals: All values of current validation.
     
     - returns: Error message.
     */
    public func errorFormat(_ val : AnyObject?, allVals : [String:AnyObject]) -> String {
        return (self.displayName ?? self.memberName) + NSLocalizedString("错误", comment: "./PMS/Classes/Extension/Validation/ModelValidation.swift")
    }
}

/**
 *  Protocol for model or entity to provide validation rules.
 */
@objc public protocol IValidationRuleProvider {
    /**
     Get validation rules
     
     - returns: Rules.
     */
    func getValidateRules() -> [ValidationRule]
}

/// Data binding/mappgin in view to provide values.
public class ViewDataMapping : NSObject {
    public var memberName : String
    /// Provide model bind value(also for validation).
    public var valueProvider : () -> AnyObject?
    /// Relation views which data bind to.
    public var views : [UIView]?
    
    /**
     Data mapping initializer.
     
     - parameter name:  Member name.
     - parameter value: Value provider for model binder.
     - parameter views: Related views, this value is optional, default value is nil. If you set this value, error behavior maybe use it for some purpose.
     
     - returns: Single member data mapping.
     */
    public init(memberName name : String, valueProvider value : @escaping () -> AnyObject?, bindViews views: [UIView]? = nil) {
        self.memberName = name
        self.valueProvider = value
        self.views = views
    }
}

/**
 *  Protocol for views to provide data binding relations.
 */
@objc
public protocol IViewDataBindingProtocol {
    func getDataMappings() -> [ViewDataMapping]
}
